package com.dlc.shop.common.filter;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import com.dlc.shop.common.config.SensitiveWordConfig;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.common.handler.HttpHandler;
import com.dlc.shop.common.handler.SensitiveHandler;
import com.dlc.shop.common.wrapper.RequestWrapper;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @author Citrus
 * @date 2021/8/17 11:05
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class SensitiveFilter implements Filter {

    Logger logger = LoggerFactory.getLogger(getClass().getName());


    private  final SensitiveHandler sensitiveHandler;
    private  final HttpHandler httpHandler;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        Set<String> sensitiveWhiteSet = SensitiveWordConfig.getSensitiveWhiteSet();
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        if (CollectionUtil.isEmpty(sensitiveWhiteSet)){
            chain.doFilter(req, resp);
            return;
        }
        for (String sensitiveUrl : sensitiveWhiteSet) {
            if (antPathMatcher.match(sensitiveUrl,req.getRequestURI())){
                chain.doFilter(req, resp);
                return;
            }
        }
        // 敏感词输入过滤
        if (StrUtil.isNotBlank(req.getContentType()) && req.getContentType().contains(ContentType.JSON.getValue())) {
            RequestWrapper requestWrapper  = new RequestWrapper(req);
            String body = requestWrapper.getBody();
            Set<String> sensitive = sensitiveHandler.isSensitive(body);
            if (StrUtil.isNotBlank(body) && CollUtil.isNotEmpty(sensitive)) {
                Iterator<String> stringIterator = sensitive.iterator();
                StringBuffer senstiveBuffer = new StringBuffer();
                while (stringIterator.hasNext()) {
                    senstiveBuffer.append(stringIterator.next()).append("、");
                }
                String senstiveString = senstiveBuffer.deleteCharAt(senstiveBuffer.length() - 1).toString();
                httpHandler.printServerResponseToWeb(new YamiShopBindException("存在敏感词: " + senstiveString + ", 请重新输入" ));
                return;
            }
            chain.doFilter(requestWrapper, resp);
        } else {
            Map<String, String[]> parameterMap = req.getParameterMap();
            StringBuilder stringBuilder = new StringBuilder();
            for (String s : parameterMap.keySet()) {
                stringBuilder.append(parameterMap.get(s)[0]);
            }
            // 传入参数是否包含敏感词,最小匹配
            Set<String> sensitive = sensitiveHandler.isSensitive(stringBuilder.toString());
            if (StrUtil.isNotBlank(stringBuilder.toString()) && CollUtil.isNotEmpty(sensitive)) {
                Iterator<String> stringIterator = sensitive.iterator();
                StringBuffer senstiveBuffer = new StringBuffer();
                while (stringIterator.hasNext()) {
                    senstiveBuffer.append(stringIterator.next()).append("、");
                }
                String senstiveString = senstiveBuffer.deleteCharAt(senstiveBuffer.length() - 1).toString();
                httpHandler.printServerResponseToWeb(new YamiShopBindException("存在敏感词: " + senstiveString + ", 请重新输入"));
                return;
            }
            chain.doFilter(req, resp);
        }
    }
}
